/*
 * @Author: chenbolin@msn.cn
 * @Date: 2023-08-04 14:14:57
 * @LastEditors: chenbolin@msn.cn
 * @LastEditTime: 2023-10-27 17:21:34
 * @FilePath: \Remote\src\Sys\Sys.c
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
 */
#include "Sys.h"
#include "SysButton.h"
#include "Button.h"
#include "Joystick.h"
#include "Wireless.h"
#include <math.h>
// #include "SysButton.h"

#define SYS_VERSION "0.0.1"
#define SYS_SETTINGS_FLAG 0x1234

#define SYS_SETTINGS_SUM_POS ((int)&gSysSettings.sumcheck - (int)&gSysSettings)

#define SYS_VALVE_CURRENT_MIN 200
#define SYS_VALVE_CURRENT_MAX 700
#define SYS_SLOW_RAISE_TIME 1000

static SysSettings_t gSysSettings;
static SysValveStep_t gValveSteps[SYS_VALVE_CH_COUNT][2];
static SysWorkMode_t gWorkMode = SYS_WORK_MODE_NORMAL;

static uint8_t checkSum(uint8_t *data, uint16_t len)
{
    uint8_t sum = 0;
    uint16_t i;

    for (i = 0; i < len; i++)
    {
        sum += data[i];
    }
    return sum;
}

uint32_t SysWirelessAddress(void)
{
    return gSysSettings.wirelessAddress;
}

void SysWirelessAddressSet(uint32_t addr)
{
    gSysSettings.wirelessAddress = addr;
    SysSettingsUpdate();
}

#define SYS_THROTTLE_ADC_MIN 1000//TODO: 
#define SYS_THROTTLE_ADC_MAX 4000
#define SYS_THROTTLE_VOLTAGE_MIN 1000
#define SYS_THROTTLE_VOLTAGE_MAX 4000

uint16_t SysThrottleValue(void)
{
    uint16_t adc = HalADCGetChannelValue(HAL_ADC_THROTTLE);
    uint32_t offset;

    if(adc > SYS_THROTTLE_ADC_MIN)
    {
        offset = (adc - SYS_THROTTLE_ADC_MIN) * (SYS_THROTTLE_VOLTAGE_MAX - SYS_THROTTLE_VOLTAGE_MIN) / (SYS_THROTTLE_ADC_MAX - SYS_THROTTLE_ADC_MIN);
        return (SYS_THROTTLE_VOLTAGE_MIN + offset);
    }
    return 0;
}

SysSpeedMode_t SysSpeedMode(void)
{
    if (ButtonGetState(BUTTON_ID_SPEED) == BUTTON_STATUS_PRESS)
    {
        return SYS_SPEED_MODE_FAST;
    }

    return SYS_SPEED_MODE_SLOW;
}

#define SYS_BATTERY_ADC_MIN 2700 // 电量ADC最小
#define SYS_BATTERY_ADC_MAX 3700 // 电量ADC最大

uint8_t SysBatteryPercentage(void)
{
    uint16_t adc = HalADCGetChannelValue(HAL_ADC_BATTERY);

    if (adc <= SYS_BATTERY_ADC_MIN)
    {
        return 0;
    }
    else if (adc >= SYS_BATTERY_ADC_MAX)
    {
        return 100;
    }

    return (adc - SYS_BATTERY_ADC_MIN) * 100 / (SYS_BATTERY_ADC_MAX - SYS_BATTERY_ADC_MIN);
}

uint8_t SysWirelessSignalLevel(void)
{
    uint8_t rssi = WirelessRSSI();

    if ((rssi >= 20) && (rssi <= 55))
        return 4;
    else if ((rssi > 55) && (rssi <= 65))
        return 3;
    else if ((rssi > 65) && (rssi <= 75))
        return 2;
    else if ((rssi > 75) && (rssi < 85))
        return 1;
    else
        return 0;
}

SysJoystickChannel_t toJoystickChannel(SysValveChannel_t ch)
{
    return (SysJoystickChannel_t)ch; //一一对应
}

uint16_t SysJoystickPercentToCurrent(SysValveChannel_t ch, SysJoystickDirect_t dir)
{
    SysValveCurrent_t *pars = &gSysSettings.current[ch][dir];
    uint16_t max, min; //
    uint8_t percent = 0;
    uint16_t current;

    if (JoystickIsReady())
    {
        percent = JoystickGetPercent(toJoystickChannel(ch), dir);
        if (percent > 0)
        {
            if (SysWorkMode() == SYS_WORK_MODE_NORMAL)
            {
                max = (SysSpeedMode() == SYS_SPEED_MODE_FAST) ? pars->fastMax : pars->slowMax;
                min = pars->min;
            }
            else //设置模式
            {
                max = SYS_VALVE_CURRENT_MAX;
                min = SYS_VALVE_CURRENT_MIN;
            }

            current = min + (uint16_t)((float)percent * (max - min) / 100.0f);
            return current;
        }
    }

    return 0;
}

void SysSettingsUpdate(void)
{
    SysSettings_t oldSettings;
    uint8_t i;

    HalFlashRead(HAL_FLASH_SETTINGS_ADDR, (uint8_t *)&oldSettings, sizeof(SysSettings_t));
    if (memcmp(&gSysSettings, &oldSettings, sizeof(SysSettings_t)) != 0) // change
    {
        gSysSettings.sumcheck = checkSum((uint8_t *)&gSysSettings, SYS_SETTINGS_SUM_POS);

        for (i = 0; i < SYS_VALVE_CH_COUNT; i++)
        {
            SysValveCurrentStepUpdate((SysValveChannel_t)i);
        }
        HalFlashErase(HAL_FLASH_SETTINGS_ADDR, sizeof(SysSettings_t));
        HalFlashWrite(HAL_FLASH_SETTINGS_ADDR, (uint8_t *)&gSysSettings, sizeof(SysSettings_t));

        /*backup*/
        HalFlashErase(HAL_FLASH_SETTINGS_BACKUP_ADDR, sizeof(SysSettings_t));
        HalFlashWrite(HAL_FLASH_SETTINGS_BACKUP_ADDR, (uint8_t *)&gSysSettings, sizeof(SysSettings_t));
    }
}

bool SysIsEmergencyStop(void)
{
    if (SysWorkMode() == SYS_WORK_MODE_NORMAL)
    {
        return (ButtonGetState(BUTTON_ID_EMERGENCY_STOP) == BUTTON_STATUS_PRESS);
    }

    return false;
}

SysSettings_t *SysSettings(void)
{
    return &gSysSettings;
}

void SysValveCurrentStepUpdate(SysValveChannel_t ch)
{
    SysSettings_t *st = &gSysSettings;
    SysValveCurrent_t *curParms;
    float upstep, downstep;

    curParms = &st->current[ch][SYS_JOYSTICK_DIR_UP];
    upstep = (curParms->fastMax - curParms->min) / (SYS_SLOW_RAISE_TIME / SYS_PERIODIC_EXECUTION_INTERVAL);
    downstep = curParms->fastMax - curParms->min;
    gValveSteps[ch][SYS_JOYSTICK_DIR_UP].fast.raise = upstep;
    gValveSteps[ch][SYS_JOYSTICK_DIR_UP].fast.descent = downstep; // 上_快速_升降

    upstep = (curParms->slowMax - curParms->min) / (SYS_SLOW_RAISE_TIME / SYS_PERIODIC_EXECUTION_INTERVAL);
    downstep = curParms->slowMax - curParms->min;
    gValveSteps[ch][SYS_JOYSTICK_DIR_UP].slow.raise = upstep;
    gValveSteps[ch][SYS_JOYSTICK_DIR_UP].slow.descent = downstep; // 上_慢速_升降

    // max-min/(delay/100)
    curParms = &gSysSettings.current[ch][SYS_JOYSTICK_DIR_DOWN];
    upstep = (curParms->fastMax - curParms->min) / (SYS_SLOW_RAISE_TIME / SYS_PERIODIC_EXECUTION_INTERVAL);
    downstep = curParms->fastMax - curParms->min;
    gValveSteps[ch][SYS_JOYSTICK_DIR_DOWN].fast.raise = upstep;
    gValveSteps[ch][SYS_JOYSTICK_DIR_DOWN].fast.descent = downstep; // 下_快速_升降

    upstep = (curParms->slowMax - curParms->min) / (SYS_SLOW_RAISE_TIME / SYS_PERIODIC_EXECUTION_INTERVAL);
    downstep = curParms->slowMax - curParms->min;
    gValveSteps[ch][SYS_JOYSTICK_DIR_DOWN].slow.raise = upstep;
    gValveSteps[ch][SYS_JOYSTICK_DIR_DOWN].slow.descent = downstep; // 下_慢速_升降
}

SysValveStep_t *SysGetValveStep(SysValveChannel_t ch, SysJoystickDirect_t dir)
{
    if (ch < SYS_VALVE_CH_COUNT)
    {
        return &gValveSteps[ch][dir];
    }
    return NULL;
}

static void settingsInit(void)
{
    SysSettings_t *st = &gSysSettings;
    SysSettings_t backup;
    // bool defaultSettings = false;
    uint8_t i;

    HalFlashRead(HAL_FLASH_SETTINGS_ADDR, (uint8_t *)st, sizeof(SysSettings_t));
    HalFlashRead(HAL_FLASH_SETTINGS_BACKUP_ADDR, (uint8_t *)&backup, sizeof(SysSettings_t));

    if (st->flag == SYS_SETTINGS_FLAG && checkSum((uint8_t *)st, SYS_SETTINGS_SUM_POS) == st->sumcheck)
    {
        if (memcmp(st, &backup, sizeof(SysSettings_t)) != 0) // different
        {
            /*backup update*/
            HalFlashErase(HAL_FLASH_SETTINGS_BACKUP_ADDR, sizeof(SysSettings_t));
            HalFlashWrite(HAL_FLASH_SETTINGS_BACKUP_ADDR, (uint8_t *)st, sizeof(SysSettings_t));
        }
    }
    else // 主数据无效
    {
        if (backup.flag == SYS_SETTINGS_FLAG && checkSum((uint8_t *)&backup, SYS_SETTINGS_SUM_POS) == backup.sumcheck)
        {
            memcpy(st, &backup, sizeof(SysSettings_t));
            HalFlashErase(HAL_FLASH_SETTINGS_ADDR, sizeof(SysSettings_t));
            HalFlashWrite(HAL_FLASH_SETTINGS_ADDR, (uint8_t *)&backup, sizeof(SysSettings_t));
        }
        else // 系统初始化或主备份数据同时被破坏
        {
            st->flag = SYS_SETTINGS_FLAG;
            st->version = 0;
            st->wirelessAddress = SYS_WIRELESS_BRAODCAST_ADDRESS;
            for (i = 0; i < SYS_VALVE_CH_COUNT; i++)
            {
                st->current[i][SYS_JOYSTICK_DIR_UP].min = 300;
                st->current[i][SYS_JOYSTICK_DIR_UP].slowMax = 450;
                st->current[i][SYS_JOYSTICK_DIR_UP].fastMax = 600;

                st->current[i][SYS_JOYSTICK_DIR_DOWN].min = 300;
                st->current[i][SYS_JOYSTICK_DIR_DOWN].slowMax = 450;
                st->current[i][SYS_JOYSTICK_DIR_DOWN].fastMax = 600;
            }

            st->sumcheck = checkSum((uint8_t *)st, SYS_SETTINGS_SUM_POS);

            HalFlashErase(HAL_FLASH_SETTINGS_ADDR, sizeof(SysSettings_t));
            HalFlashWrite(HAL_FLASH_SETTINGS_ADDR, (uint8_t *)st, sizeof(SysSettings_t));

            /*backup update*/
            HalFlashErase(HAL_FLASH_SETTINGS_BACKUP_ADDR, sizeof(SysSettings_t));
            HalFlashWrite(HAL_FLASH_SETTINGS_BACKUP_ADDR, (uint8_t *)st, sizeof(SysSettings_t));
        }
    }

    for (i = 0; i < SYS_VALVE_CH_COUNT; i++)
    {
        SysValveCurrentStepUpdate((SysValveChannel_t)i);
    }
}

SysDeviceType_t SysDeviceType(void)
{
    return SYS_DEVICE_TYPE_ZBD;
}

char *SysVersion(void)
{
    return SYS_VERSION;
}

SysWorkMode_t SysWorkMode(void)
{
    return gWorkMode;
}

static void lowLevelInit(void)
{
    settingsInit();

    /*工作模式
     * 默认为正常模式
     * 急停、启动、熄火同时按下开机进入配置模式
     */
    if (ButtonGetState(BUTTON_ID_EMERGENCY_STOP) == BUTTON_STATUS_PRESS &&
        ButtonGetState(BUTTON_ID_ENGINE_START) == BUTTON_STATUS_PRESS &&
        ButtonGetState(BUTTON_ID_ENGINE_STOP) == BUTTON_STATUS_PRESS)
    {
        gWorkMode = SYS_WORK_MODE_CONFIG;
    }
}

extern void UserMainInitialize(void);
extern void UserMainPoll(void);
void SysInitialize(void)
{
    HalInitialize();
    lowLevelInit();
    SysButtonInitialize();
    UserMainInitialize();
}

void SysPoll(void)
{
    HalPoll();
    SysButtonPoll();
    UserMainPoll();
}
